package com.lekang.service.impl;

import java.util.List;
import com.lekang.common.utils.DateUtils;
import com.lekang.service.ITaskArrangementService;
import com.lekang.service.ITaskGenerationService;
import com.lekang.service.IBillService;
import com.lekang.service.IRefundRecordService;
import com.lekang.domain.RefundRecord;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.lekang.mapper.OrderManagementMapper;
import com.lekang.domain.OrderManagement;
import com.lekang.service.IOrderManagementService;

/**
 * 订单管理Service业务层处理
 * 
 * @author ruitong
 * @date 2025-10-13
 */
@Service
public class OrderManagementServiceImpl implements IOrderManagementService 
{
    private static final Logger log = LoggerFactory.getLogger(OrderManagementServiceImpl.class);
    
    @Autowired
    private OrderManagementMapper orderManagementMapper;
    
    @Autowired
    private ITaskGenerationService taskGenerationService;

    @Autowired
    private ITaskArrangementService taskArrangementService;

    @Autowired
    private IBillService billService;

    @Autowired
    private IRefundRecordService refundRecordService;

    /**
     * 查询订单管理
     * 
     * @param id 订单管理主键
     * @return 订单管理
     */
    @Override
    public OrderManagement selectOrderManagementById(Long id)
    {
        return orderManagementMapper.selectOrderManagementById(id);
    }

    @Override
    public List<OrderManagement> selectOrderManagementListApp(OrderManagement orderManagement) {
        return orderManagementMapper.selectOrderManagementListApp(orderManagement);
    }

    @Override
    public OrderManagement selectOrderManagementByOrderNO(String orderNO) {
        return orderManagementMapper.selectOrderManagementByOrderNo(orderNO);
    }

    /**
     * 查询订单管理列表
     * 
     * @param orderManagement 订单管理
     * @return 订单管理
     */
    @Override
    public List<OrderManagement> selectOrderManagementList(OrderManagement orderManagement)
    {
        return orderManagementMapper.selectOrderManagementList(orderManagement);
    }

    /**
     * 新增订单管理
     * 
     * 说明：
     * 1. 自动生成账单：当系统生成订单后，自动将订单转成账单
     * 2. 订单与账单的对应规则是1:1，每一笔订单都会生成账单
     * 3. 账单生成失败会回滚事务
     * 
     * @param orderManagement 订单管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertOrderManagement(OrderManagement orderManagement)
    {
        try {
            // 1. 新增订单
            orderManagement.setCreateTime(DateUtils.getNowDate());
            int result = orderManagementMapper.insertOrderManagement(orderManagement);
            
            if (result > 0) {
                // 2. 订单创建成功后，自动生成费用账单
                log.info("订单ID: {} 创建成功，开始生成费用账单", orderManagement.getId());
                boolean billResult = billService.generateBillForOrder(orderManagement.getId());
                
                if (!billResult) {
                    log.error("订单ID: {} 费用账单生成失败", orderManagement.getId());
                    throw new RuntimeException("费用账单生成失败");
                }
                log.info("订单ID: {} 费用账单生成成功", orderManagement.getId());
            }
            
            return result;
        } catch (Exception e) {
            log.error("新增订单失败，订单编号: {}", orderManagement.getOrderNo(), e);
            throw e;
        }
    }

    /**
     * 修改订单管理
     * 
     * 说明：
     * 1. 如果订单状态变为"已支付"，会自动生成护理计划外任务
     * 2. 订单状态改变时，会同步更新关联的费用账单状态
     * 3. 任务生成失败会回滚事务
     * 
     * @param orderManagement 订单管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateOrderManagement(OrderManagement orderManagement)
    {
        try {
            if (orderManagement.getId()==null){
                OrderManagement orderManagement1 = orderManagementMapper.selectOrderManagementByOrderNo(orderManagement.getOrderNo());
                orderManagement.setId(orderManagement1.getId());
            }
            
            // 1. 查询原订单状态（用于判断状态是否变化）
            OrderManagement oldOrder = orderManagementMapper.selectOrderManagementById(orderManagement.getId());
            Long oldStatus = oldOrder != null ? oldOrder.getOrderStatus() : null;
            Long newStatus = orderManagement.getOrderStatus();
            Long newTransactionStatus = orderManagement.getTransactionStatus();
            
            // 1.5 检测退款场景（小程序传入：orderStatus=4, transactionStatus=2 或 orderStatus=5, transactionStatus=3）
            if (newStatus != null && newTransactionStatus != null) {
                // 退款场景1：orderStatus=4, transactionStatus=2（小程序当前逻辑）
                // 退款场景2：orderStatus=5, transactionStatus=3（新逻辑）
                boolean isRefund = (newStatus == 4L && newTransactionStatus == 2L) || 
                                  (newStatus == 5L && newTransactionStatus == 3L);
                
                if (isRefund) {
                    log.info("检测到退款操作：订单ID={}, 订单号={}", orderManagement.getId(), oldOrder.getOrderNo());
                    
                    // 创建退款记录
                    RefundRecord refundRecord = new RefundRecord();
                    refundRecord.setOrderId(oldOrder.getId());
                    refundRecord.setOrderNo(oldOrder.getOrderNo());
                    // 生成退款编号：TK + 时间戳
                    refundRecord.setRefundNo("TK" + System.currentTimeMillis());
                    refundRecord.setRefundAmount(oldOrder.getOrderAmount());
                    refundRecord.setApplicant(oldOrder.getOrderUserId());
                    refundRecord.setApplicationTime(new Date());
                    refundRecord.setRefundTime(new Date());
                    refundRecord.setRefundStatus(0L); // 退款成功
                    refundRecord.setRefundReason(orderManagement.getCancelReason());
                    refundRecord.setRefundChannel("小程序");
                    refundRecord.setRefundMethod("原路退回");
                    
                    log.info("准备创建退款记录：订单编号={}, 退款金额={}, 退款原因={}", 
                        oldOrder.getOrderNo(), oldOrder.getOrderAmount(), orderManagement.getCancelReason());

                    // 插入退款记录（会自动更新余额）
                    int refundInsertResult = refundRecordService.insertRefundRecord(refundRecord);
                    log.info("退款记录插入结果：{}", refundInsertResult);
                }
            }
            
            // 2. 更新订单
            orderManagement.setUpdateTime(DateUtils.getNowDate());
            int result = orderManagementMapper.updateOrderManagement(orderManagement);

            // 3. 如果订单状态发生变化，同步更新关联的费用账单状态
            if (result > 0 && newStatus != null && !newStatus.equals(oldStatus)) {
                log.info("订单ID: {} 状态从 {} 变更为 {}，开始同步更新费用账单状态", 
                    orderManagement.getId(), oldStatus, newStatus);
                
                String orderNo = orderManagement.getOrderNo();
                if (orderNo == null && oldOrder != null) {
                    orderNo = oldOrder.getOrderNo();
                }
                
                if (orderNo != null) {
                    billService.updateBillStatusByOrderStatus(orderNo, newStatus);
                    log.info("订单ID: {} 关联的费用账单状态同步完成", orderManagement.getId());
                }
            }

            return result;
        } catch (Exception e) {
            log.error("更新订单失败，订单ID: {}", orderManagement.getId(), e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateOrderManagementByOrderNo(OrderManagement orderManagement) {
        try {
            // 查询订单信息
            OrderManagement dbOrder = orderManagementMapper.selectOrderManagementByOrderNo(orderManagement.getOrderNo());
            if (dbOrder == null) {
                throw new RuntimeException("未找到订单：" + orderManagement.getOrderNo());
            }
            
            // 1. 查询原订单状态
            OrderManagement oldOrder = orderManagementMapper.selectOrderManagementById(dbOrder.getId());
            
            // 2. 判断是退款还是支付
            Long newOrderStatus = orderManagement.getOrderStatus();
            Long newTransactionStatus = orderManagement.getTransactionStatus();
            
            // 如果是退款（订单状态为5-已关闭，交易状态为3-退款成功）
            if (newOrderStatus != null && newOrderStatus == 5L && newTransactionStatus != null && newTransactionStatus == 3L) {
                log.info("检测到退款操作：订单号={}", orderManagement.getOrderNo());
                
                // 3. 创建退款记录
                RefundRecord refundRecord = new RefundRecord();
                refundRecord.setOrderId(dbOrder.getId());
                refundRecord.setOrderNo(dbOrder.getOrderNo());
                // 生成退款编号：TK + 时间戳
                refundRecord.setRefundNo("TK" + System.currentTimeMillis());
                refundRecord.setRefundAmount(dbOrder.getOrderAmount());
                refundRecord.setApplicant(dbOrder.getOrderUserId());
                refundRecord.setApplicationTime(new Date());
                refundRecord.setRefundTime(new Date());
                refundRecord.setRefundStatus(0L); // 退款成功
                refundRecord.setRefundReason(orderManagement.getCancelReason());
                refundRecord.setRefundChannel("小程序");
                refundRecord.setRefundMethod("原路退回");
                
                log.info("准备创建退款记录：订单编号={}, 退款金额={}, 退款原因={}", 
                    dbOrder.getOrderNo(), dbOrder.getOrderAmount(), orderManagement.getCancelReason());

                // 4. 插入退款记录（会自动更新余额）
                int refundInsertResult = refundRecordService.insertRefundRecord(refundRecord);
                log.info("退款记录插入结果：{}", refundInsertResult);
            }
            
            // 5. 更新订单状态
            dbOrder.setOrderStatus(newOrderStatus);
            dbOrder.setTransactionStatus(newTransactionStatus);
            if (orderManagement.getCancelReason() != null) {
                dbOrder.setCancelReason(orderManagement.getCancelReason());
            }
            dbOrder.setUpdateTime(DateUtils.getNowDate());
            
            int result = orderManagementMapper.updateOrderManagement(dbOrder);

            // 6. 同步更新关联的费用账单状态
            if (result > 0 && dbOrder.getTransactionStatus() != null) {
                Long currentTransactionStatus = dbOrder.getTransactionStatus();
                Long oldTransactionStatus = oldOrder != null ? oldOrder.getTransactionStatus() : null;

                // 如果交易状态发生变化，同步更新费用账单状态
                if (oldTransactionStatus == null || !currentTransactionStatus.equals(oldTransactionStatus)) {
                    log.info("订单ID: {} 交易状态从 {} 变更为 {}，开始同步更新费用账单状态", 
                        dbOrder.getId(), oldTransactionStatus, currentTransactionStatus);
                    
                    String orderNo = dbOrder.getOrderNo();
                    if (orderNo != null) {
                        billService.updateBillStatusByOrderStatus(orderNo, dbOrder.getOrderStatus());
                        log.info("订单ID: {} 关联的费用账单状态同步完成", dbOrder.getId());
                    }
                }

                // 状态从非已支付变为已支付（假设1表示已支付）- 生成护理任务
                if (Long.valueOf(1).equals(currentTransactionStatus) && !Long.valueOf(1).equals(oldTransactionStatus)) {
                    log.info("订单ID: {} 支付完成，开始生成护理任务", dbOrder.getId());
                    int taskResult = taskGenerationService.generateTaskForOrder(dbOrder.getId());
                    log.info("订单ID: {} 任务生成成功，结果: {}", dbOrder.getId(), taskResult);
                }
            }

            return result;
        } catch (Exception e) {
            log.error("更新订单失败，订单号：{}", orderManagement.getOrderNo(), e);
            throw e;
        }
    }

    /**
     * 批量删除订单管理
     * 
     * @param ids 需要删除的订单管理主键
     * @return 结果
     */
    @Override
    public int deleteOrderManagementByIds(Long[] ids)
    {
        return orderManagementMapper.deleteOrderManagementByIds(ids);
    }

    /**
     * 删除订单管理信息
     * 
     * @param id 订单管理主键
     * @return 结果
     */
    @Override
    public int deleteOrderManagementById(Long id)
    {
        return orderManagementMapper.deleteOrderManagementById(id);
    }

    /**
     * 根据账单状态更新订单状态
     * 
     * 说明：
     * 1. 当费用账单状态改变时，同步更新对应的订单状态
     * 2. 通过账单的relatedOrder字段找到关联的订单
     * 3. 根据账单交易状态映射对应的订单状态
     * 
     * @param billNo 账单编号
     * @param transactionStatus 账单交易状态
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderStatusByBillStatus(String billNo, String transactionStatus) {
        try {
            log.info("开始根据账单编号: {} 更新订单状态，账单交易状态: {}", billNo, transactionStatus);
            
            // 1. 查询账单信息，获取关联的订单编号
            // 需要通过billMapper查询账单获取relatedOrder
            // 由于这里没有直接注入billMapper，我们通过billService查询
            com.lekang.domain.Bill queryBill = new com.lekang.domain.Bill();
            queryBill.setBillNo(billNo);
            List<com.lekang.domain.Bill> billList = billService.selectBillList(queryBill);
            
            if (billList == null || billList.isEmpty()) {
                log.warn("未找到账单编号: {} 的账单记录", billNo);
                return false;
            }
            
            com.lekang.domain.Bill bill = billList.get(0);
            
            // 2. 检查是否是费用账单
            if (!"费用账单".equals(bill.getBillType())) {
                log.debug("账单编号: {} 不是费用账单，跳过订单状态同步", billNo);
                return false;
            }
            
            // 3. 获取关联的订单编号
            String orderNo = bill.getRelatedOrder();
            if (orderNo == null || orderNo.trim().isEmpty()) {
                log.warn("账单编号: {} 未关联订单，无法更新订单状态", billNo);
                return false;
            }
            
            // 4. 查询订单信息
            OrderManagement order = orderManagementMapper.selectOrderManagementByOrderNo(orderNo);
            if (order == null) {
                log.warn("未找到订单编号: {} 的订单记录", orderNo);
                return false;
            }
            
            // 5. 根据账单交易状态映射订单状态
            Long newOrderStatus = getOrderStatusByTransactionStatus(transactionStatus);
            
            // 6. 只有状态发生变化时才更新
            if (!newOrderStatus.equals(order.getOrderStatus())) {
                OrderManagement updateOrder = new OrderManagement();
                updateOrder.setId(order.getId());
                updateOrder.setOrderStatus(newOrderStatus);
                updateOrder.setUpdateTime(DateUtils.getNowDate());
                
                int result = orderManagementMapper.updateOrderManagement(updateOrder);
                if (result > 0) {
                    log.info("订单ID: {} 状态已更新为: {}", order.getId(), newOrderStatus);
                }
            } else {
                log.debug("订单ID: {} 状态未发生变化，跳过更新", order.getId());
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("根据账单编号: {} 更新订单状态失败", billNo, e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int refundByOrderNo(OrderManagement orderManagement) {
        try {
            // 1. 根据订单号查询订单（校验订单是否存在）
            OrderManagement dbOrder = orderManagementMapper.selectOrderManagementByOrderNo(orderManagement.getOrderNo());
            if (dbOrder == null) {
                throw new RuntimeException("未找到订单：" + orderManagement.getOrderNo());
            }

            // 2. 校验订单状态（允许待支付、待执行状态退款）
            if (dbOrder.getOrderStatus() != 0 && dbOrder.getOrderStatus() != 1) { 
                throw new RuntimeException("仅待支付或待执行状态的订单可退款");
            }

            // 3. 创建退款记录
            RefundRecord refundRecord = new RefundRecord();
            refundRecord.setOrderId(dbOrder.getId());
            refundRecord.setOrderNo(dbOrder.getOrderNo());
            // 生成退款编号：TK + 时间戳
            refundRecord.setRefundNo("TK" + System.currentTimeMillis());
            refundRecord.setRefundAmount(dbOrder.getOrderAmount());
            refundRecord.setApplicant(dbOrder.getOrderUserId());
            refundRecord.setApplicationTime(new Date());
            refundRecord.setRefundTime(new Date());
            refundRecord.setRefundStatus(0L); // 退款成功
            refundRecord.setRefundReason(orderManagement.getCancelReason());
            refundRecord.setRefundChannel("小程序");
            refundRecord.setRefundMethod("原路退回");
            
            log.info("准备创建退款记录：订单编号={}, 退款金额={}, 退款原因={}", 
                dbOrder.getOrderNo(), dbOrder.getOrderAmount(), orderManagement.getCancelReason());

            // 4. 插入退款记录（会自动更新余额）
            int refundInsertResult = refundRecordService.insertRefundRecord(refundRecord);
            log.info("退款记录插入结果：{}", refundInsertResult);

            // 5. 更新订单状态为已关闭(5)，交易状态为退款成功(3)
            dbOrder.setOrderStatus(5L);
            dbOrder.setTransactionStatus(3L);
            dbOrder.setUpdateTime(DateUtils.getNowDate());
            dbOrder.setCancelReason(orderManagement.getCancelReason());
            
            // 6. 执行更新（调用按订单号更新的SQL）
            int result = orderManagementMapper.updateOrderManagementByOrderNo(dbOrder);

            // 7. 同步更新账单状态（退款场景）
            if (result > 0) {
                billService.updateBillStatusByOrderStatus(dbOrder.getOrderNo(), dbOrder.getOrderStatus());
            }

            return result;
        } catch (Exception e) {
            log.error("退款失败，订单号：{}", orderManagement.getOrderNo(), e);
            throw e;
        }

    }

    /**
     * 根据账单交易状态获取订单状态
     * 
     * @param transactionStatus 账单交易状态
     * @return 订单状态
     */
    private Long getOrderStatusByTransactionStatus(String transactionStatus) {
        if (transactionStatus == null) {
            return 0L; // 默认待支付
        }
        
        // 账单状态对应关系：
        // 账单状态 0-待支付 -> 订单状态 0-待支付
        // 账单状态 1-已支付 -> 订单状态 1-待执行
        // 账单状态 2-已关闭 -> 订单状态 5-已关闭
        
        switch (transactionStatus) {
            case "0":
                return 0L; // 待支付
            case "1":
                return 1L; // 待执行（已支付后的默认状态）
            case "2":
                return 5L; // 已关闭
            default:
                return 0L; // 默认待支付
        }
    }
}
